package cn.array;

/**
 * 动态数组设计
 *
 * @author Mxb
 * @version 1.0
 * @date 2020/3/5 14:15
 */
public class DyArrayList<E> {

    /**
     * 包含2个成员变量
     */
    private int size; //数组容量
    private E[] elements;

    private static final int DEfault_Capaticy = 16;

    /**
     * 提供有参构造方法
     *
     * @param capaticy
     */
    public DyArrayList(int capaticy) {
        if (capaticy < DEfault_Capaticy) {
            elements = (E[]) new Object[DEfault_Capaticy];

        } else {
            // 根据传入的 数组容量创建数组容量的大小
            elements = (E[]) new Object[capaticy];
        }
    }

    /**
     * 提供无参的构造方法
     */
    public DyArrayList() {
        // 设置数组默认的容量为 10
        //elements = new int[DEfault_Capaticy];
        this(DEfault_Capaticy);
    }


    /**
     * 清空数组中的元素
     */
    public void clear() {
        // 当数组中存放的是 对象类型的时候
        // 循环清空对象
        for (int i = 0; i < size; i++) {
            elements[i] = null;
        }
        size = 0;
    }

    /**
     * 返回元素的数量
     *
     * @return
     */
    public int size() {
        return size;
    }

    /**
     * 数组是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 判断数组是否包含某个元素
     *
     * @param ele
     * @return
     */
    public boolean contains(E ele) {
        // 有就返回 true
        if (indexOf(ele) != -1) {
            return true;
        }
        return false;
    }

    /**
     * 获取index处的值
     *
     * @param index
     * @return
     */
    public E get(int index) {
        rangeCheck(index);

        return elements[index];
    }

    /**
     * 设置index处的值
     *
     * @param index
     * @param ele
     * @return 返回被替换的元素
     */
    public E set(int index, E ele) {
        rangeCheck(index);
        E old = elements[index];
        elements[index] = ele;
        return old;
    }

    /**
     * 添加元素到数组末尾
     */
    public void add(E ele) {
        //elements[size] = ele;
        //size++;
        add(size, ele);
    }

    /**
     * 在固定索引位置添加元素
     *
     * @param index
     * @param ele
     */
    public void add(int index, E ele) {
        // 判断索引
        rangeCheckForAdd(index);
        //扩容
        ensureCapacity(size + 1);


        // 把数组中的元素 逐个右移
        for (int i = size - 1; i >= index; i--) {
            elements[i + 1] = elements[i];
        }
        // 索引处添加新元素
        elements[index] = ele;
        size++;
    }

    /**
     * 移除索引处的元素
     *
     * @param index
     * @return
     */
    public E remove(int index) {
        rangeCheck(index);

        // 记录以前的元素
        E old = elements[index];
        // 把元素逐个 往左移动
        for (int i = index + 1; i <= size - 1; i++) {
            elements[i - 1] = elements[i];
        }
        size--;
        // 移除 对象时的 操作
        elements[size] = null;

        // 把移除的元素 返回
        return elements[index];
    }

    /**
     * 查看元素的索引位置
     *
     * @param ele
     * @return
     */
    public int indexOf(E ele) {
        // 是否可以存放 null 元素   可以
        if (ele == null) {
            for (int i = 0; i < size; i++) {
                if (elements[i] == null) {
                    return i;
                }
            }
        } else {  // 非null时
            for (int i = 0; i < size; i++) {
                if (elements[i].equals(ele)) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 打印数组
     *
     * @return
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("size=" + size + "," + "[");

        // 循环数组
        for (int i = 0; i < size; i++) {
            sb.append(elements[i]);
            if (i != size - 1) {
                sb.append(",");
            }
        }

        sb.append("]");
        return sb.toString();
    }

    /**
     * 检查范围
     *
     * @param index
     */
    private void rangeCheck(int index) {
        // 判断索引
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界！" + index + " Size:" + size);
        }
    }

    /**
     * 检查添加时 数组的范围
     *
     * @param index
     */
    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("添加索引越界！" + index + " Size:" + size);
        }
    }

    /**
     * 保证要有capacity的容量
     *
     * @param capacity
     * @return
     */
    private void ensureCapacity(int capacity) {
        int oldCapacity = elements.length;
        if (oldCapacity >= capacity) return;
        // 扩容1.5倍
        int newCapacity = oldCapacity * 2;
        // 创建新 数组
        E[] newElements = (E[]) new Object[newCapacity];
        // 将元素复制到 扩容后的数组
        for (int i = 0; i < size; i++) {
            newElements[i] = elements[i];
        }
        elements = newElements;
        //System.out.println(elements.length);
        //System.out.println(newElements.length);
        System.out.println("容量：" + oldCapacity + "扩容为：" + newCapacity);

    }
}
